////////////////////////////////////////////////////////////////////////////////
//
//  MICROSOFT CORPORATION
//  Copyright (c) Microsoft Corporation.
//  All Rights Reserved.
//
//  NOTICE: Microsoft Confidential. Intended for Internal Use Only.
//
////////////////////////////////////////////////////////////////////////////////

package com.msn.beet.logging
{

import com.msn.beet.errors.UnsupportedMethodException;
import com.msn.beet.events.LocalConnectionEvent;

import flash.events.AsyncErrorEvent;
import flash.events.IEventDispatcher;
import flash.events.SecurityErrorEvent;
import flash.events.StatusEvent;
import flash.net.LocalConnection;
import flash.utils.getQualifiedClassName;

/**
 * Abstract class for communicating with LocalConnectionHandler. Override
 * "transmit" to specify how data "_loggerLocalConnection", and sets itself
 * as the client, override "transmit" to specify how data is to be handled.
 *
 * <p>Captures error events and error level status events broadcast by
 * LocalConnection and throws them as LocalConnectionError(s) with specific
 * Id and original error or event.</p>
 *
 * @see LocalConnectionHandler
 * @see com.msn.beet.logging.Message
 * @see com.msn.beet.events.LocalConnectionEvent
 *
 */
public class AbstractLocalConnectionClient implements IEventDispatcher
{
    include "../core/Version.as";
    include "../events/EventDispatcherMixin.as";

    public static const ERROR_ID_CONN_ALREADY_OPEN:uint = 2082;
    public static const EVENT_LEVEL_ERROR:String = "error";

    protected var LOCAL_CONNECTION_ID:String = "_loggerLocalConnection";
    protected var connection:LocalConnection = new LocalConnection();

    /**
     * Initializes connection to "_loggerLocalConnection", and sets itself
     * as the client. Dispatches
     * <code>LocalConnectionEvent#MULTIPLE_CONNECTIONS_ERROR_EVENT</code>.
     */
    public function AbstractLocalConnectionClient()
    {
        connection.client = this;
        connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR,
                                    asyncErrorHandler);
        connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR,
                                    securityErrorHandler);
        connection.addEventListener(StatusEvent.STATUS, statusErrorHandler);

        try
        {
            connection.connect(LOCAL_CONNECTION_ID);
        }
        catch(e:ArgumentError)
        {
            if (e.errorID == ERROR_ID_CONN_ALREADY_OPEN)
            {
                var msg:String = "LocalConnectionError - " +
                                 "\"_loggerLocalConnection\" is already " +
                                 "opened, check that multiple instances of " +
                                 "this client are not running.";
                this.dispatchEvent(new LocalConnectionEvent(
                    LocalConnectionEvent.MULTIPLE_CONNECTIONS_ERROR_EVENT,
                    msg));
            }

        }
    }

    /**
     * @param content       The values passed to the Log utility.
     * @param level         The log level of the logging event.
     * @param upTime        The number of milliseconds after the document
     *                      class is initialized.
     * @param timeStamp     The time the log event occured.
     * @param className     The class in which the log call occured.
     * @param line          The line number at which the log call occured.
     *
     * @throws flash.errors.IllegalOperationError Must override method
     */
    public function transmit(content:Array /* of Object */, logLevelName:String,
                             upTime:int, timeStamp:Date, className:String,
                             line:int):void
    {
        throw new UnsupportedMethodException("Abstract method.");
    }

    /**
     * Dispatches LocalConnectionEvent.ASYNCH_ERROR_EVENT
     */
    protected function asyncErrorHandler(e:AsyncErrorEvent):void
    {
        var msg:String = "AsyncErrorEvent in " + getQualifiedClassName(this);
        this.dispatchEvent(new LocalConnectionEvent(
            LocalConnectionEvent.ASYNCH_ERROR_EVENT, msg, e));
    }

    /**
     * Dispatches LocalConnectionEvent.SECURITY_ERROR_EVENT
     */
    protected function securityErrorHandler(e:SecurityErrorEvent):void
    {
        var msg:String = "SecurityErrorEvent in " + getQualifiedClassName(this);
        this.dispatchEvent(new LocalConnectionEvent(
            LocalConnectionEvent.SECURITY_ERROR_EVENT, msg, e))
    }

    /**
     * Dispatches LocalConnectionEvent.STATUS_ERROR_EVENT
     */
    protected function statusErrorHandler(e:StatusEvent):void
    {
        if (e.level == EVENT_LEVEL_ERROR)
        {
            var msg:String = "Error level StatusEvent in " +
                              getQualifiedClassName(this);
            this.dispatchEvent(new LocalConnectionEvent(
                LocalConnectionEvent.STATUS_ERROR_EVENT, msg, e))
        }
    }

}

}
